package old.galaxyGeneration;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;

import objects.GameSettings;
import objects.Universe;

import inputOutput.PlayerSettings;
import inputOutput.XMLoader;

public abstract class Galaxy {
	
	//XML supplied
	//--------------------------------------------------------------
	protected int starLimit; //Hard limit on the total number of stars allowed;
	private int maxStarsInit; //Limits on initial number of stars in a galaxy
	protected int minStarsInit; 
	protected int gridMultiplier;// = 1;  //number of grid lines per light year
	private double[] systemTypeRatio;  //Single, Binary, Trinary, Quad, Neutron, Black holes, Antimatter
	
	/* Dwarfs, sub-dwarfs, Main sequence, Sub-Giants, Giants, Bright Giants, 
	 * Supergiants*/
	private double[] starSpectrumAvg;
	private double[] starSpectrumYoung; 
	private double[] starSpectrumOld;
	private double[] starSpectrum;
	//--------------------------------------------------------------
	
	
	//User supplied (playerSettings)
	//--------------------------------------------------------------	
	protected int numStars;  //30 to 3000
	protected String age;  //young, average, old
	protected double earthLike;  //0.0 to 0.1
	protected int randomnessDial;  //0 to 6
	protected boolean slowZone;  //1 = yes, 0 = no
	protected String galaxyPattern;	
	//--------------------------------------------------------------
	
	//Class-only
	//--------------------------------------------------------------
	protected int[][] starGrid;  //used for placement of stars on map
	protected int uniLength;  //universe Length, in ly
	protected int workingLength;  //actual working space where stars are to be placed.  Prevents cut-off	
	
	protected Random randG1 = new Random();
	protected Random randG2 = new Random();
	protected Random randUni = new Random();
	
	protected int starsPlaced = 0; //number of stars put on map
	protected int centersPlaced = 0; //for multicluster, number of cluster centers put on map
	
	protected int x = 0;  //x coord of object within starGrid
	protected int y = 0;  //y coord in object within starGrid
	protected double tempX = 0;
	protected double tempY = 0;
	
	protected double ringOne = 0.1;  //probability of placing a star in a 1s ring
	protected double ringTwo = 0.2;
	
	protected Universe universe;
	//--------------------------------------------------------------
	
	public Galaxy(){};

	public Galaxy(GameSettings gameSettings, Universe theUniverse)	
	{
		this.numStars = gameSettings.getNumStars();
		this.age = gameSettings.getAge();
		this.earthLike = gameSettings.getEarthLike();
		this.randomnessDial = gameSettings.getRandomnessDial();
		this.slowZone = gameSettings.isSlowZone();
		this.galaxyPattern = gameSettings.getGalaxyPattern();
		
		this.universe = theUniverse;
		
		if (age.equalsIgnoreCase("old"))
			starSpectrum = gameSettings.getStarSpectrumOld();
		else if (age.equalsIgnoreCase("young"))
			starSpectrum = gameSettings.getStarSpectrumYoung();
		else
			starSpectrum = gameSettings.getStarSpectrumAvg();
		
		
		uniLength = (int)Math.round(2*numStars); //2*numStars/1.4142
		if (uniLength%2 > 0)
			{uniLength+=1;}
		
		//expand to appropriate number of grid points
		//uniLength *= gridMultiplier;
		starGrid = new int[uniLength][uniLength];		

		workingLength = uniLength/2;
	}
	
	protected abstract void galaxyGenerator();
	
	public void updateGrid(int x, int y)
	{
		//Center region
		starGrid[x][y] = 3;

		//fill in 3s
		starGrid[x+1][y] = (starGrid[x+1][y] < 3) ? (3):(starGrid[x+1][y]);
		starGrid[x+1][y+1] = (starGrid[x+1][y+1] < 3) ? (3):(starGrid[x+1][y+1]);
		starGrid[x+1][y-1] = (starGrid[x+1][y-1] < 3) ? (3):(starGrid[x+1][y-1]);
		starGrid[x][y+1] = (starGrid[x][y+1] < 3) ? (3):(starGrid[x][y+1]);
		starGrid[x][y-1] = (starGrid[x][y-1] < 3) ? (3):(starGrid[x][y-1]);
		starGrid[x-1][y] = (starGrid[x-1][y] < 3) ? (3):(starGrid[x-1][y]);
		starGrid[x-1][y+1] = (starGrid[x-1][y+1] < 3) ? (3):(starGrid[x-1][y+1]);
		starGrid[x-1][y-1] = (starGrid[x-1][y-1] < 3) ? (3):(starGrid[x-1][y-1]);

		for (int i=x-2; i<x+3; i++)
		{
			starGrid[i][y+2] = (starGrid[i][y+2] < 3) ? (3):(starGrid[i][y+2]);
			starGrid[i][y-2] = (starGrid[i][y-2] < 3) ? (3):(starGrid[i][y-2]);
		}

		for (int i=y-1; i<y+2; i++)
		{
			starGrid[x-2][i] = (starGrid[x-2][i] < 3) ? (3):(starGrid[x-2][i]);
			starGrid[x+2][i] = (starGrid[x+2][i] < 3) ? (3):(starGrid[x+2][i]);
		}

		//fill in 2s
		for (int i=x-3; i<x+4; i++)
		{
			starGrid[i][y+3] = (starGrid[i][y+3] < 2) ? (2):(starGrid[i][y+3]);
			starGrid[i][y-3] = (starGrid[i][y-3] < 2) ? (2):(starGrid[i][y-3]);
		}

		for (int i=y-2; i<y+3; i++)
		{
			starGrid[x-3][i] = (starGrid[x-3][i] < 2) ? (2):(starGrid[x-3][i]);
			starGrid[x+3][i] = (starGrid[x+3][i] < 2) ? (2):(starGrid[x+3][i]);
		}
		
		//fill in 1s
		for (int i=x-4; i<x+5; i++)
		{
			starGrid[i][y+4] = (starGrid[i][y+4] < 1) ? (1):(starGrid[i][y+3]);
			starGrid[i][y-4] = (starGrid[i][y-4] < 1) ? (1):(starGrid[i][y-3]);
		}

		for (int i=y-3; i<y+4; i++)
		{
			starGrid[x-4][i] = (starGrid[x-4][i] < 1) ? (1):(starGrid[x-3][i]);
			starGrid[x+4][i] = (starGrid[x+4][i] < 1) ? (1):(starGrid[x+3][i]);
		}
		
		
		
	}




	public int getStarLimit() {
		return starLimit;
	}

	public void setStarLimit(int starLimit) {
		this.starLimit = starLimit;
	}

	public int getMaxStarsInit() {
		return maxStarsInit;
	}

	public void setMaxStarsInit(int maxStarsInit) {
		this.maxStarsInit = maxStarsInit;
	}

	public int getGridMultiplier() {
		return gridMultiplier;
	}

	public void setGridMultiplier(int gridMultiplier) {
		this.gridMultiplier = gridMultiplier;
	}

	public double[] getSystemTypeRatio() {
		return systemTypeRatio;
	}

	public void setSystemTypeRatio(double[] systemTypeRatio) {
		this.systemTypeRatio = systemTypeRatio;
	}

	public double[] getStarSpectrumAvg() {
		return starSpectrumAvg;
	}

	public void setStarSpectrumAvg(double[] starSpectrumAvg) {
		this.starSpectrumAvg = starSpectrumAvg;
	}

	public double[] getStarSpectrumYoung() {
		return starSpectrumYoung;
	}

	public void setStarSpectrumYoung(double[] starSpectrumYoung) {
		this.starSpectrumYoung = starSpectrumYoung;
	}

	public double[] getStarSpectrumOld() {
		return starSpectrumOld;
	}

	public void setStarSpectrumOld(double[] starSpectrumOld) {
		this.starSpectrumOld = starSpectrumOld;
	}

	public int getMinStarsInit() {
		return minStarsInit;
	}

	public void setMinStarsInit(int minStarsInit) {
		this.minStarsInit = minStarsInit;
	}
	
	
	

}
